package main

import (
	"fmt"
	"log"
	"net/url"
	"reflect"
	"strings"
	"time"

	client "github.com/influxdata/influxdb1-client"
)

func main() {

	//NewClientConn("127.0.0.1", 8086, "guozheng","123456")
	//ExampleNewClient()
	//ExampleClient_Ping()
	//ExampleClient_Query()
	//ExampleClient_Write()
	//c := GetConnection("127.0.0.1", 8086, "", "")
	//datas := Query(c, "select time,host from test","test")

	//tag := map[string]string{
	//	"tag_one": "tag111",
	//	"tag_two": "tag222",
	//}
	//
	//f := map[string]interface{}{
	//	"field1": "f1",
	//}
	//
	//Insert(c, tag, f, "tableA", "test")
	//
	//Query(c, "select * from testTable","BumbeBeeTuna")
	//delete(c, "delete from tableA where time=1562399213", "test")

	//ts := Query(c, "select * from tableA", "test", TestStruct{})
	//fmt.Println(ts[0])
	//fmt.Println(ts[1])
	test := TestStruct{
		TagOne: "111",
	}
	fmt.Println(reflect.TypeOf(test))
	fmt.Println(reflect.ValueOf(TestStruct{}).Type())
}

func GetConnection(ip string, port int, username string, password string) client.Client {
	host, err := url.Parse(fmt.Sprintf("http://%s:%d", ip, port))
	if err != nil {
		fmt.Println(err)
		log.Fatal(err)
		return client.Client{}
	}

	conf := client.Config{
		URL:      *host,
		Username: "guozheng",
		Password: "123456",
	}

	con, err := client.NewClient(conf)
	if err != nil {
		fmt.Println(err)
		log.Fatal(err)
		return client.Client{}
	}

	return *con
}

func Insert(c client.Client, tags map[string]string, fields map[string]interface{}, measurement string, database string) bool {
	p := client.Point{
		Measurement: measurement,
		Tags:        tags,
		Fields:      fields,
		Time:        time.Now(),
		Precision:   "s",
	}

	pts := make([]client.Point, 1)
	pts[0] = p

	bps := client.BatchPoints{
		Points:   pts,
		Database: database,
		//RetentionPolicy: "default",
	}

	_, err := c.Write(bps)
	if err != nil {
		log.Fatal(err)
		return false
	}
	return true
}

func BatchInsert(c client.Client, tags []map[string]string, fields []map[string]interface{}, measurement string, database string) bool {

	ps := make([]client.Point, len(tags))

	for i := 0; i < len(tags); i++ {
		ps[i] = client.Point{
			Measurement: measurement,
			Tags:        tags[i],
			Fields:      fields[i],
			Time:        time.Now(),
			Precision:   "s",
		}
	}

	bps := client.BatchPoints{
		Points:   ps,
		Database: database,
		//RetentionPolicy: "default",
	}

	_, err := c.Write(bps)
	if err != nil {
		log.Fatal(err)
		return false
	}
	return true
}

func Query(c client.Client, sql string, database string, s interface{}) []interface{} {

	q := client.Query{
		Command:  sql,
		Database: database,
	}

	if response, err := c.Query(q); err == nil && response.Error() == nil {
		rs := response.Results
		if len(rs) <= 0 {
			return nil
		}
		ss := rs[0].Series
		if len(ss) <= 0 {
			return nil
		}

		e0 := make([]interface{}, 0)

		for i := 0; i < len(ss[0].Values); i++ {
			data := ss[0].Values[i]
			bean := reflect.New(reflect.ValueOf(s).Type()).Elem()

			for j := 0; j < len(ss[0].Columns); j++ {

				colName := ss[0].Columns[j]
				name := convertToBeanColName(colName)

				sf, _ := reflect.TypeOf(s).FieldByName(name)

				colType := sf.Type.Name()

				if colType == "string" {
					bean.Field(j).SetString(data[j].(string))
				}

				if colType == "int" {
					bean.Field(j).SetInt(data[j].(int64))
				}

			}
			e0 = append(e0, bean)
		}

		return e0

	}

	return nil
}

func delete(c client.Client, sql string, database string) bool {
	q := client.Query{
		Command:  sql,
		Database: database,
	}
	_, err := c.Query(q)
	if err != nil {
		log.Println(err)
		return false
	}
	return true
}

func convertToBeanColName(colName string) string {

	if strings.Contains(colName, "_") {
		cs := strings.Split(colName, "_")
		first := cs[1][0:1]
		first = strings.ToUpper(first)
		name := strings.ToUpper(cs[0][0:1]) + cs[0][1:] + first + cs[1][1:]
		return name
	} else {
		return strings.ToUpper(colName[0:1]) + colName[1:]
	}

	return colName
}

type TestStruct struct {
	Time   string
	Field1 string
	TagOne string
	TagTwo string
}
